home *** CD-ROM | disk | FTP | other *** search
- /* $Id: COMCamS.cpp 1.6 1997/04/11 03:38:36 damien Exp $ */
-
- ////////////////////////////////////////////////////////////////////////
- // First Camera Example : Spherical Camera //
- //--------------------------------------------------------------------//
- // Implementation of the Spherical Camera Interface //
- ////////////////////////////////////////////////////////////////////////
-
- // Copyright (c) 1995, Ray Dream, Inc. All rights reserved.
-
- #include "math.h"
-
- #ifndef __COMCAMS__
- #include "COMCAMS.h"
- #endif
-
- #ifndef __CAMSDLL__
- #include "CAMSDLL.h"
- #endif
-
- #ifndef __3DCOFAIL__
- #include "3DCoFail.h"
- #endif
-
- // Global value for Unit Conversion and Angle limits
- NUM3D InternalZoom = 10000.0;
- NUM3D kQuick180 = 180.0; //3.1415926535897932384626233; // 180 deg.
- NUM3D kRadToDeg = 180.0/3.1415926535897932384626233;
- NUM3D kQuick288 = 288.0;
-
-
-
- // Tool to get the Global Coordinates from the Local Coordinates
- void LocalToGlobal(TRANSFORM3D* transform,VECTOR3D* LocalPos,VECTOR3D* GlobalPos) {
- // Axes rotations
- (*GlobalPos)[0]=transform->fR.fix*(*LocalPos)[0]
- +transform->fR.fjx*(*LocalPos)[1]
- +transform->fR.fkx*(*LocalPos)[2];
- (*GlobalPos)[1]=transform->fR.fiy*(*LocalPos)[0]
- +transform->fR.fjy*(*LocalPos)[1]
- +transform->fR.fky*(*LocalPos)[2];
- (*GlobalPos)[2]=transform->fR.fiz*(*LocalPos)[0]
- +transform->fR.fjz*(*LocalPos)[1]
- +transform->fR.fkz*(*LocalPos)[2];
- // Unit conversion : Points Units to 3D Units
- (*GlobalPos)[0] /= 288.0;
- (*GlobalPos)[1] /= 288.0;
- (*GlobalPos)[2] /= 288.0;
- // Origin translation
- (*GlobalPos)[0] += transform->fT[0];
- (*GlobalPos)[1] += transform->fT[1];
- (*GlobalPos)[2] += transform->fT[2];
- }
-
- // Tool to get the Global Coordinates from the Local Coordinates for a Vector
- void LocalToGlobalVector(TRANSFORM3D* transform,VECTOR3D* LocalPos,VECTOR3D* GlobalPos) {
- // Axes rotations
- (*GlobalPos)[0]=transform->fR.fix*(*LocalPos)[0]
- +transform->fR.fjx*(*LocalPos)[1]
- +transform->fR.fkx*(*LocalPos)[2];
- (*GlobalPos)[1]=transform->fR.fiy*(*LocalPos)[0]
- +transform->fR.fjy*(*LocalPos)[1]
- +transform->fR.fky*(*LocalPos)[2];
- (*GlobalPos)[2]=transform->fR.fiz*(*LocalPos)[0]
- +transform->fR.fjz*(*LocalPos)[1]
- +transform->fR.fkz*(*LocalPos)[2];
- // Unit conversion : Points Units to 3D Units
- (*GlobalPos)[0] /= 288.0;
- (*GlobalPos)[1] /= 288.0;
- (*GlobalPos)[2] /= 288.0;
- }
-
- // Tool to get the Local Coordinates from the Global Coordinates
- void GlobalToLocal(TRANSFORM3D* transform,VECTOR3D* GlobalPos,VECTOR3D* LocalPos) {
- // Origin translation
- (*GlobalPos)[0] -= transform->fT[0];
- (*GlobalPos)[1] -= transform->fT[1];
- (*GlobalPos)[2] -= transform->fT[2];
- // Unit conversion : 3D Units to Points Units
- (*GlobalPos)[0] *= 288.0;
- (*GlobalPos)[1] *= 288.0;
- (*GlobalPos)[2] *= 288.0;
-
- // Axes rotations
- (*LocalPos)[0]=transform->fR.fix*(*GlobalPos)[0]
- +transform->fR.fiy*(*GlobalPos)[1]
- +transform->fR.fiz*(*GlobalPos)[2];
- (*LocalPos)[1]=transform->fR.fjx*(*GlobalPos)[0]
- +transform->fR.fjy*(*GlobalPos)[1]
- +transform->fR.fjz*(*GlobalPos)[2];
- (*LocalPos)[2]=transform->fR.fkx*(*GlobalPos)[0]
- +transform->fR.fky*(*GlobalPos)[1]
- +transform->fR.fkz*(*GlobalPos)[2];
- }
-
- // Tool to get the Local Coordinates from the Global Coordinates for a Vector
- void GlobalToLocalVector(TRANSFORM3D* transform,VECTOR3D* GlobalPos,VECTOR3D* LocalPos) {
- // Unit conversion : 3D Units to Points Units
- (*GlobalPos)[0] *= 288.0;
- (*GlobalPos)[1] *= 288.0;
- (*GlobalPos)[2] *= 288.0;
-
- // Axes rotations
- (*LocalPos)[0]=transform->fR.fix*(*GlobalPos)[0]
- +transform->fR.fiy*(*GlobalPos)[1]
- +transform->fR.fiz*(*GlobalPos)[2];
- (*LocalPos)[1]=transform->fR.fjx*(*GlobalPos)[0]
- +transform->fR.fjy*(*GlobalPos)[1]
- +transform->fR.fjz*(*GlobalPos)[2];
- (*LocalPos)[2]=transform->fR.fkx*(*GlobalPos)[0]
- +transform->fR.fky*(*GlobalPos)[1]
- +transform->fR.fkz*(*GlobalPos)[2];
- }
-
-
-
-
-
- #undef INTERFACE
- #define INTERFACE SphereCamera
- // Constructor / Destructor of the C++ Object :
- SphereCamera::SphereCamera() {
- fCRef=0; // Reference Counter
- // Rotation matrix initialized to identity :
- fTransform.fR.fix=fTransform.fR.fjy=fTransform.fR.fkz=1.0;
- fTransform.fR.fjx=fTransform.fR.fkx=0.0;
- fTransform.fR.fiy=fTransform.fR.fky=0.0;
- fTransform.fR.fiz=fTransform.fR.fjz=0.0;
- // Translation vector initialized to zero :
- fTransform.fT[0]=fTransform.fT[1]=fTransform.fT[2]=0.0;
- // Data initialisation :
- fData.fZoomCoef=10; // 10xZoom Factor
- fData.fAngle =360; // Visible space in degree
- QuickAngle=((NUM3D)fData.fAngle)/2; // Half Angle : the limits are -QuickAngle to +QuickAngle
- QuickZoom =fData.fZoomCoef; // NUM3D Value of Zoom for calculation
- Coef=QuickZoom*kQuick288/InternalZoom*kQuick180/QuickAngle; // Unit conversion factor
- }
-
- SphereCamera::~SphereCamera() {
- global_count_Obj--;
- }
-
- // IUnknown Interface :
- HRESULT SphereCamera::QueryInterface(THIS_ REFIID riid,LPVOID FAR* ppvObj) {
- *ppvObj=NULL;
-
- // The SphereCamera knows the interfaces of the parent Objects
- if (IsEqualIID(riid, IID_IUnknown))
- *ppvObj=(LPVOID)this;
- else if (IsEqualIID(riid, IID_I3DExCamera))
- *ppvObj=(LPVOID)this;
- else if (IsEqualIID(riid, IID_I3DExDataExchanger))
- *ppvObj=(LPVOID)this;
- else if (IsEqualIID(riid, IID_I3DExtension))
- *ppvObj=(LPVOID)this;
-
- // we must add reference if we return an interface
- if (*ppvObj!=NULL) {
- ((LPUNKNOWN)*ppvObj)->AddRef();
- return NOERROR;
- }
- else {
- return ResultFromScode(E_NOINTERFACE);
- }
- }
-
- ULONG SphereCamera::AddRef(THIS) {
- return fCRef++;
- }
-
- ULONG SphereCamera::Release(THIS) {
- ULONG UnreleaseObject=fCRef--;
-
- if (fCRef==0)
- delete this; // No reference left, so destroy the object
-
- return UnreleaseObject;
- // local variable used, because fCRef can be destroyed before.
- }
-
- // I3DExtension methods :
- I3DExtension* SphereCamera::Clone(THIS) {
- SphereCamera* theClone = new SphereCamera;
- if (theClone) {
- theClone->AddRef();
- theClone->fTransform=fTransform; // Copy Data and internal coefficient.
- theClone->fData =fData;
- theClone->QuickAngle=QuickAngle;
- theClone->QuickZoom =QuickZoom;
- theClone->Coef =Coef;
- }
- return theClone;
- }
-
- HRESULT SphereCamera::ShellUtilitiesInit(THIS_ IShUtilities* shellUtilities) {
- InitCoFailure(shellUtilities);
- return NOERROR;
- }
-
- // I3DExDataExchanger methods :
- ExtensionDataMap* SphereCamera::GetExtensionDataMap(THIS) {
- return NULL;
- }
-
- void* SphereCamera::GetExtensionDataBuffer(THIS) {
- return &fData; // used by the shell to set the new parameters
- }
-
- HRESULT SphereCamera::ExtensionDataChanged(THIS) {
- QuickZoom=fData.fZoomCoef;
- QuickAngle=((NUM3D)fData.fAngle)/2; // The Shell considers the total angle
- // but the Camera goes from -QuickAngle to +QuickAngle
- Coef=QuickZoom*kQuick288/InternalZoom*kQuick180/QuickAngle;
- // recalculate the different factors.
- return NOERROR;
- }
-
- HRESULT SphereCamera::HandleEvent(THIS_ ULONG SourceID) {
- return ResultFromScode(E_NOTIMPL);
- }
-
- short SphereCamera::GetResID(THIS) {
- return 130; // this is the view ID in the resource file.
- }
-
- // I3DExCamera methods :
- HRESULT SphereCamera::SetTransform(THIS_ TRANSFORM3D* transform) {
- fTransform=*transform; // Copy the data of transform and not the pointer.
- return NOERROR;
- }
-
- // Ray Creation :
- BOOLEAN SphereCamera::CreateRay(THIS_ VECTOR2D* screenPosition, VECTOR3D* resultOrigin, VECTOR3D* resultDirection) {
- VECTOR3D SpherePos;
- NUM3D theta,phi,sintheta,costheta,sinphi,cosphi;
-
- SpherePos[0]=SpherePos[1]=SpherePos[2]=0.0;
- LocalToGlobal(&fTransform,&SpherePos,resultOrigin);
- // Origin of the Ray is the center of the Sphere.
-
- theta=(*screenPosition)[0]/Coef;
- phi =(*screenPosition)[1]/Coef;
-
-
- sintheta=sin(theta / kRadToDeg);
- costheta=cos(theta / kRadToDeg); //QuickSinCos(theta,sintheta,costheta);
- sinphi=sin(phi / kRadToDeg);
- cosphi=cos(phi / kRadToDeg); //QuickSinCos(phi,sinphi,cosphi);
-
- SpherePos[0]=sintheta*cosphi;
- SpherePos[1]=sinphi;
- SpherePos[2]=-costheta*cosphi;
- // 3D Coordinates (x,y,z) from Spherical coordinates (r=1,theta,phi)
-
- LocalToGlobalVector(&fTransform,&SpherePos,resultDirection);
- NUM3D norm=sqrt(SQR((*resultDirection)[0]) + SQR((*resultDirection)[1]) + SQR((*resultDirection)[2]));
- (*resultDirection)[0] /= norm;
- (*resultDirection)[1] /= norm;
- (*resultDirection)[2] /= norm;
- //resultDirection->Normalize(*resultDirection);
- // Direction vector must be in Global Coordinates System and Normalized
-
- // Angle selection :
- if (theta>QuickAngle || theta<-QuickAngle) {
- return FALSE; // Not in front of the camera
- }
- if (phi>QuickAngle/2 || phi<-QuickAngle/2) {
- return FALSE; // Not in front of the camera
- }
-
- return TRUE;
- }
-
-
- // 3D Projection :
- BOOLEAN SphereCamera::Project3DTo2D(THIS_ VECTOR3D* position, VECTOR2D* resultScreenPosition, NUM3D* resultDistanceToScreen) {
- VECTOR3D tempV;
- NUM3D theta,phi,x2,z2,r,norm;
-
- norm=sqrt(SQR((*position)[0]) + SQR((*position)[1]) + SQR((*position)[2]));
- tempV[0]=(*position)[0]/norm;
- tempV[1]=(*position)[1]/norm;
- tempV[2]=(*position)[2]/norm;
- //position->Normalize(tempV);
-
- // Get the Spherical coordinates : ro,theta,phi
- x2=tempV[0]*tempV[0];
- z2=tempV[2]*tempV[2];
- r=x2+z2;
- r=sqrt(r); // Must be calculate to get phi
-
- theta=atan2(tempV[0], -tempV[2]) * kRadToDeg; //QuickArcSinCos(tempV[0],-tempV[2],theta);
- phi=atan2(tempV[1], r) * kRadToDeg; //QuickArcSinCos(tempV[1],r,phi);
-
- if (theta>kQuick180) {
- theta-=kQuick180*2; // theta : -180∞ to 180∞ (theta - 360)
- }
- if (phi>kQuick180) {
- phi-=kQuick180*2; // phi : -90∞ to 90∞
- }
-
- (*resultScreenPosition)[0]=theta*Coef;
- (*resultScreenPosition)[1]=phi*Coef;
- *resultDistanceToScreen=sqrt(SQR((*position)[0]) + SQR((*position)[1]) + SQR((*position)[2]));
- //*resultDistanceToScreen=position->GetNorm();
-
- // Angle selection :
- /*if ((theta>QuickAngle)||(theta<-QuickAngle)) {
- return FALSE;
- }
- if ((phi>(QuickAngle>>1))||(phi<-(QuickAngle>>1))) {
- return FALSE;
- }*/
-
- return TRUE;
- }
-
- ULONG SphereCamera::GetPrimitiveID(THIS) {
- return 0;
- }
-
- ULONG SphereCamera::Clip3D(THIS_ FACET3D* localFacet, VERTEX3D* localVertices,
- FACET3D* cameraFacet, VERTEX3D* cameraVertices,
- NUM3D* clipBox) {
- return 0; /*** to do ***/
- }
-
- BOOLEAN SphereCamera::ClipLine3D(THIS_ VECTOR3D* P1, VECTOR3D* P2) {
- return FALSE; /*** to do ***/
- }
-